home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 April: Mac OS SDK / Dev.CD Apr 97 SDK1.toast / Development Kits (Disc 1) / Macintosh Drag and Drop / Demo Applications / FinderDrag / FinderStuff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-09  |  17.0 KB  |  678 lines  |  [TEXT/MPS ]

  1.  
  2. #include <Icons.h>
  3. #include <Aliases.h>
  4. #include <AERegistry.h>
  5. #include <Gestalt.h>
  6. #include <AEPackObject.h>
  7. #include <AEObjects.h>
  8. #include <Errors.h>
  9. #include <TextUtils.h>
  10.  
  11. #define DEBUGLEVEL DEBUGFULL
  12. #include "Exceptions.h"
  13. #include "FinderStuff.h"
  14.  
  15.  
  16. AEDesc pFinderTarget;
  17.  
  18.  
  19.  
  20. Size GetSizeFromIconType(OSType iconType);
  21.  
  22.  
  23. //----------------------------------------------------------------------------
  24. // FailOSErr
  25. //----------------------------------------------------------------------------
  26. void FailOSErr(OSErr err)
  27. {
  28.     if (err != noErr) {
  29.         Str255    str;
  30.         
  31.         NumToString(err, str);
  32.         DebugStr(str);
  33.     }
  34. }
  35.  
  36.  
  37. //----------------------------------------------------------------------------
  38. // InitFinderAE
  39. //----------------------------------------------------------------------------
  40. OSErr InitFinderAE()
  41. {
  42.     OSErr    err;
  43.     DescType finderSig = 'MACS';
  44.  
  45.     err = AECreateDesc(typeApplSignature, (Ptr) &finderSig,
  46.         sizeof(DescType), &pFinderTarget);
  47.  
  48.     check(err == noErr);
  49.     return err;
  50. }
  51.  
  52.  
  53. //----------------------------------------------------------------------------
  54. // BuildHFSDescList
  55. //----------------------------------------------------------------------------
  56. OSErr BuildHFSDescList(DragReference theDrag, AEDescList *hfsList)
  57. {
  58.     ItemReference    itemRef;
  59.     Size            dataSize;
  60.     FSSpec            theFile;
  61.     OSErr            err;
  62.     unsigned short    numItems, counter;    
  63.  
  64.     err = AECreateList(NULL, 0, false, hfsList);
  65.  
  66.     CountDragItems(theDrag, &numItems);
  67.         
  68.     for (counter = 1; counter <= numItems; counter++) {
  69.         err = GetDragItemReferenceNumber(theDrag, counter, &itemRef);
  70.  
  71.         dataSize = sizeof(FSSpec);
  72.         err = GetFlavorData(theDrag, kRealSpecItemRef, flavorTypeRealSpec, 
  73.                                             &theFile, &dataSize, 0);
  74.                                     
  75.         if (err == noErr) {
  76.             //
  77.             // This is an hfs flavor object, put it in the file list.
  78.             //
  79.             err = AddSpecToDescList(hfsList, &theFile);
  80.         }
  81.     }
  82.  
  83.     check(err == noErr);
  84.     return err;
  85. }
  86.  
  87.  
  88. //----------------------------------------------------------------------------
  89. // HandleDragCloneMove
  90. //
  91. // Walk the drag items and collect the items in it.  Then move them to
  92. // the location pointed to by the full pathname (only for now, of course).
  93. //----------------------------------------------------------------------------
  94. OSErr HandleDragCloneMove(DragReference theDrag)
  95. {
  96.     AEDescList    fileDescList;
  97.     OSErr        err;
  98.     FSSpec        descSpec;
  99.     Point        globalPt;
  100.     short        modifiers;
  101.     Boolean        moveIt;
  102.     
  103.     moveIt = true;
  104.     err = paramErr;
  105.     require(HaveScriptableFinder(), ScriptableFinderDead);
  106.  
  107.     err = BuildHFSDescList(theDrag, &fileDescList);
  108.     require(err == noErr, BuildHFSDescList);
  109.     
  110.     err = GetDropFSSpec(theDrag, &descSpec);
  111.     require(err == noErr, GetDropFSSpec);
  112.     
  113.     err = GetDragModifiers(theDrag, &modifiers, NULL, NULL);
  114.     check(err == noErr);
  115.     if (err == noErr)
  116.         moveIt = !(modifiers & optionKey);
  117.  
  118.     (void) GetDragMouse(theDrag, &globalPt, NULL);
  119.     err = CloneMoveDescList(&fileDescList, &descSpec, globalPt, false, moveIt);
  120.  
  121. GetDropFSSpec:
  122. BuildHFSDescList:
  123. ScriptableFinderDead:
  124.     return err;
  125. }
  126.  
  127.  
  128. //----------------------------------------------------------------------------
  129. // FinderIsRunning
  130. //
  131. // Walk the Process Mgr list to check if the Finder is running
  132. //----------------------------------------------------------------------------
  133. Boolean FinderIsRunning()
  134. {
  135.     OSErr            err;
  136.     ProcessInfoRec    pInfo;
  137.     ProcessSerialNumber    psn;
  138.     Boolean            foundIt;
  139.  
  140.     foundIt = false;
  141.     psn.highLongOfPSN = 0; psn.lowLongOfPSN = kNoProcess;
  142.  
  143.     while ((foundIt == false) && (GetNextProcess(&psn) == noErr)) {
  144.         pInfo.processName         = NULL;
  145.         pInfo.processAppSpec     = NULL;
  146.         pInfo.processInfoLength    = sizeof(ProcessInfoRec);
  147.     
  148.         err = GetProcessInformation(&psn, &pInfo);
  149.     
  150.         if ((err == noErr) 
  151.             && (pInfo.processSignature == 'MACS') 
  152.             && (pInfo.processType == 'FNDR'))
  153.             
  154.             foundIt = true;
  155.     }
  156.     
  157.     return foundIt;
  158. }
  159.  
  160.  
  161. //----------------------------------------------------------------------------
  162. // HaveScriptableFinder
  163. //
  164. // We have it if the Gestalt bit is set and the Finder is running
  165. //----------------------------------------------------------------------------
  166. Boolean HaveScriptableFinder()
  167. {
  168.     long         response;
  169.     Boolean        haveScriptableFinder;
  170.     OSErr        err;
  171.  
  172.     haveScriptableFinder = false;
  173.     
  174.     err = Gestalt(gestaltFinderAttr, &response);
  175.     require(err == noErr, Gestalt);
  176.  
  177.     if ((response & (1 << gestaltOSLCompliantFinder)) && (FinderIsRunning()))
  178.         haveScriptableFinder = true;
  179.  
  180. Gestalt:
  181.     return haveScriptableFinder;
  182. }
  183.  
  184.  
  185. //----------------------------------------------------------------------------
  186. // SendAppleEvent
  187. //----------------------------------------------------------------------------
  188. OSErr SendAppleEvent(AppleEvent *ae, AppleEvent *reply, AESendMode sendMode)
  189. {
  190.     AppleEvent    throwAwayReply;
  191.     OSErr        err;
  192.  
  193.     if (reply == NULL) {
  194.         err = AESend(ae, &throwAwayReply, sendMode, 
  195.                     kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
  196.         if (err == noErr)
  197.             AEDisposeDesc(&throwAwayReply);
  198.     }
  199.     else
  200.         err = AESend(ae, reply, sendMode, 
  201.                     kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
  202.  
  203.     check(err == noErr);
  204.     return err;
  205. }
  206.  
  207.  
  208. //----------------------------------------------------------------------------
  209. // MakeAppleEvent
  210. //----------------------------------------------------------------------------
  211. OSErr MakeAppleEvent(AEEventClass aeClass, AEEventID aeID, 
  212.             AEDesc *target, AppleEvent *ae)
  213. {
  214.     OSErr    err;
  215.     
  216.     err = AECreateAppleEvent(aeClass, aeID, target, 
  217.             kAutoGenerateReturnID, kAnyTransactionID, ae);
  218.     
  219.     check(err == noErr);
  220.     return err;
  221. }
  222.  
  223.  
  224. //----------------------------------------------------------------------------
  225. // AddSpecToDescList
  226. //
  227. // Pass this a created descriptor list.
  228. //----------------------------------------------------------------------------
  229. OSErr AddSpecToDescList(AEDescList *descList, FSSpecPtr theSpec)
  230. {
  231.     OSErr    err;
  232.     AEDesc    fileDesc;
  233.     AliasHandle    fileAlias;
  234.  
  235.     // Init the desc handles    
  236.     fileAlias                    = NULL;
  237.     fileDesc.dataHandle            = NULL;
  238.                     
  239.     err = NewAlias(NULL, theSpec, &fileAlias);
  240.     require(err == noErr, NewAlias);
  241.  
  242.     HLock((Handle) fileAlias);
  243.     err = AECreateDesc(typeAlias, (Ptr) *fileAlias, 
  244.                 GetHandleSize((Handle) fileAlias), &fileDesc);
  245.     HUnlock((Handle) fileAlias);
  246.     require(err == noErr, AECreateDesc);
  247.  
  248.     err = AEPutDesc(descList, 0, &fileDesc);
  249.  
  250. AECreateDesc:
  251. NewAlias:
  252.     if (fileDesc.dataHandle != NULL)    (void) AEDisposeDesc(&fileDesc);
  253.     if (fileAlias != NULL)                DisposeHandle((Handle) fileAlias);
  254.     
  255.     return err;
  256. }
  257.  
  258.  
  259. //----------------------------------------------------------------------------
  260. // MakeSpecifierForSelection
  261. //----------------------------------------------------------------------------
  262.  
  263. OSErr MakeSpecifierForSelection(AEDesc *selectionSpecifier)
  264. {
  265.     OSErr         err;
  266.     DescType     descData;
  267.     AEDesc        keyData, nullDescriptor;
  268.     
  269.     nullDescriptor.descriptorType = typeNull;
  270.     nullDescriptor.dataHandle = NULL;
  271.  
  272.     //
  273.     // Make a descriptor whose type is 'typeType' and whose
  274.     // contents are 'pSelection' (defined in FinderRegistry.h).
  275.     // This descriptor specifies the property of the null container
  276.     // that we are interested in--in this case, the selection.
  277.     //
  278.     descData = pSelection;
  279.     err = AECreateDesc(typeType, (Ptr) &descData, sizeof(DescType), &keyData);
  280.     require(err == noErr, AECreateDesc);
  281.     
  282.     err = CreateObjSpecifier(cProperty, &nullDescriptor, formPropertyID,
  283.                                     &keyData, true, selectionSpecifier);
  284.  
  285. AECreateDesc:
  286.     return err;
  287. }
  288.  
  289.  
  290. //----------------------------------------------------------------------------
  291. // GetIconSuiteFromFinder
  292. //
  293. // Send a GetData AE for the 'ifam'
  294. //----------------------------------------------------------------------------
  295. OSErr GetIconSuiteFromFinder(FSSpecPtr hfsObj, Handle *iconSuite)
  296. {
  297.     OSErr        err;
  298.     AppleEvent    finderEvent, replyEvent;
  299.     AEDesc        fileSpecifier, iconPropertySpecifier;
  300.     DescType    returnType;
  301.     Size        returnSize;
  302.     long        returnLong;
  303.     AEDesc        iconFamily;
  304.  
  305.     //
  306.     // Set up our locals for easy cleanup
  307.     //
  308.     *iconSuite = NULL;
  309.  
  310.     //
  311.     // Make sure the Finder is scriptable and is running.
  312.     //
  313.     err = paramErr;
  314.     require(HaveScriptableFinder() == true, HaveScriptableFinder);
  315.  
  316.     //
  317.     // Make a GetData Apple event to send to the Finder
  318.     //
  319.     err = MakeAppleEvent(kAECoreSuite, kAEGetData, &pFinderTarget, 
  320.                 &finderEvent);
  321.     require(err == noErr, MakeAppleEvent);
  322.     
  323.     //
  324.     // Make an object specifier for the interesting file
  325.     //
  326.     err = MakeSpecifierForFile(hfsObj, &fileSpecifier);
  327.     require(err == noErr, MakeSpecifierForFile);
  328.     
  329.     //
  330.     // Make an icon family property specifier for the file
  331.     //
  332.     err = MakePropertySpecifierForSpecifier(pIconBitmap, &fileSpecifier, 
  333.                 &iconPropertySpecifier);
  334.     require(err == noErr, MakePropertySpecifierForSpecifier);
  335.     
  336.     //
  337.     // Stuff it in the Apple event and send it
  338.     //
  339.     err = AEPutParamDesc(&finderEvent, keyDirectObject, &iconPropertySpecifier);
  340.     require(err == noErr, AEPutParamDesc);
  341.  
  342.     err = SendAppleEvent(&finderEvent, &replyEvent,
  343.                 kAEWaitReply + kAECanInteract + kAECanSwitchLayer);
  344.     require(err == noErr, SendAppleEvent);
  345.     
  346.     //
  347.     // Now the Finder may have sent us an error number
  348.     //
  349.     err = AEGetParamPtr(&replyEvent, keyErrorNumber, typeLongInteger, 
  350.                         &returnType, &returnLong, sizeof(long), &returnSize);
  351.     if (err == noErr)
  352.         err = (OSErr) returnLong;
  353.  
  354.     else {        
  355.         //
  356.         // If not, get the icon family and build an icon suite
  357.         //
  358.         err = AEGetParamDesc(&replyEvent, keyDirectObject, typeWildCard, &iconFamily);    
  359.         require(err == noErr, AEGetParamDesc);
  360.     
  361.         err = BuildIconSuiteFromAEDesc(true, iconSuite, &iconFamily);
  362.         check(err == noErr);
  363.     }
  364.  
  365.     //
  366.     // Clean up and exit
  367.     //
  368.     (void) AEDisposeDesc(&iconFamily);
  369.  
  370. AEGetParamDesc:
  371.     (void) AEDisposeDesc(&replyEvent);
  372.  
  373. SendAppleEvent:
  374. AEPutParamDesc:
  375.     (void) AEDisposeDesc(&iconPropertySpecifier);
  376.  
  377. MakePropertySpecifierForSpecifier:
  378.     (void) AEDisposeDesc(&fileSpecifier);
  379.  
  380. MakeSpecifierForFile:
  381.     (void) AEDisposeDesc(&finderEvent);
  382.  
  383. MakeAppleEvent:
  384. HaveScriptableFinder:
  385.     return err;
  386. }
  387.  
  388.  
  389. //----------------------------------------------------------------------------
  390. // GetSizeFromIconType
  391. //----------------------------------------------------------------------------
  392. Size GetSizeFromIconType(DescType iconType)
  393. {
  394.     Size    size = -1;
  395.  
  396.     switch (iconType) {
  397.         case large8BitData:
  398.             size = kLarge8BitIconSize;
  399.             break;
  400.         case large4BitData:
  401.             size = kLarge4BitIconSize;        
  402.             break;
  403.         case large1BitMask:
  404.             size = kLargeIconSize;
  405.             break;
  406.         case small8BitData:
  407.             size = kSmall8BitIconSize;
  408.             break;
  409.         case small4BitData:
  410.             size = kSmall4BitIconSize;
  411.             break;
  412.         case small1BitMask:
  413.             size = kSmallIconSize;
  414.             break;
  415.     }
  416.     return size;
  417. }
  418.  
  419.  
  420. //----------------------------------------------------------------------------
  421. // BuildIconSuiteFromAEDesc
  422. //
  423. // OK, this uses the Apple Event Manager to pick the icon data out of the
  424. // 'ifam' AEDesc.
  425. //----------------------------------------------------------------------------
  426. OSErr BuildIconSuiteFromAEDesc(Boolean largeIcons, Handle *iconSuite, AEDesc *iconFam)
  427. {
  428.     OSErr        err;
  429.     Handle         suite, icon;
  430.     AERecord    rec;
  431.     Ptr            buffer;
  432.     DescType    large[3] = {large8BitData, large4BitData, large1BitMask};
  433.     DescType    small[3] = {small8BitData, small4BitData, small1BitMask};
  434.     DescType    *type, iconType, typeCode;
  435.     long        count;
  436.     Size        maxSize, size, iconSize;
  437.     Boolean        maskAdded;
  438.     DescType    maskType;
  439.  
  440.     maskAdded = false;
  441.     suite = NULL;
  442.     maxSize = kLarge8BitIconSize;
  443.  
  444.     if (largeIcons == true) {
  445.         type = large;
  446.         maskType = large1BitMask;
  447.     }
  448.     else {
  449.         type = small;
  450.         maskType = small1BitMask;
  451.     }
  452.  
  453.     buffer = NewPtr(maxSize);
  454.     require(buffer != NULL, NewPtr);
  455.     
  456.     err = NewIconSuite(&suite);
  457.     require(err == noErr, NewIconSuite);
  458.     
  459.     err = AECoerceDesc(iconFam, typeAERecord, (AEDesc *) &rec);
  460.     require(err == noErr, AECoerceDesc);
  461.     
  462.     for (count = 0; count < 3; count ++) {
  463.         //
  464.         // loop through the icons and grab the data from the AERecord for
  465.         // each type of icon we're interested in.
  466.         //
  467.         iconType = type[count];
  468.         size = GetSizeFromIconType(iconType);
  469.         err = AEGetKeyPtr(&rec, iconType, iconType, &typeCode, 
  470.                         buffer, maxSize, &iconSize);
  471.     
  472.         if (err == noErr) {
  473.             //
  474.             // We don't set the error code for this unless the NewHandle
  475.             // call fails, because it's possible that the 'ifam' doesn't
  476.             // have an icon for one that we're interested in.
  477.             //
  478.             icon = NewHandle(size);
  479.     
  480.             if (icon != NULL) {
  481.                 //
  482.                 // OK, the memory alloc succeeded and we have data. Copy
  483.                 // it into the allocated icon and add it to the suite. 
  484.                 // Set atLeastOne to true, to indicate later that we did
  485.                 // in fact add at least one icon to this suite.
  486.                 //
  487.                 BlockMoveData(buffer, *icon, size);
  488.                 err = AddIconToSuite(icon, suite, iconType);
  489.                 if ((err == noErr) && (iconType == maskType))
  490.                     maskAdded = true;
  491.             }
  492.             else
  493.                 err = memFullErr;
  494.         }
  495.     }
  496.  
  497.     (void) AEDisposeDesc(&rec);
  498.  
  499. AECoerceDesc:
  500.     if ((err != noErr) || (maskAdded == false)) {
  501.         //
  502.         // There was either an error in a memory allocation,  or something
  503.         // else went wrong (like no mask was added to the suite).  Get
  504.         // rid of the partially created suite.
  505.         //
  506.         DisposeIconSuite(suite, true);
  507.         suite = NULL;
  508.     }
  509.  
  510. NewIconSuite:
  511.     DisposePtr(buffer);
  512.  
  513. NewPtr:
  514.     *iconSuite = suite;
  515.     return err;
  516. }
  517.  
  518.  
  519. //----------------------------------------------------------------------------
  520. // MakeSpecifierForFile
  521. //----------------------------------------------------------------------------
  522. OSErr MakeSpecifierForFile(FSSpecPtr hfsObj, AEDesc *fileSpecifier)
  523. {
  524.     OSErr        err;
  525.     AEDesc        nullDesc, hfsData;
  526.     AliasHandle    fileAlias;
  527.  
  528.     //
  529.     // Create the file descriptor with the FSSpec passed in.
  530.     //
  531.     err = NewAlias(NULL, hfsObj, &fileAlias);
  532.     require(err == noErr, NewAlias);
  533.  
  534.     HLock((Handle) fileAlias);
  535.     err = AECreateDesc(typeAlias, (Ptr) *fileAlias, 
  536.                 GetHandleSize((Handle) fileAlias), &hfsData);
  537.     HUnlock((Handle) fileAlias);
  538.     DisposeHandle((Handle) fileAlias);
  539.     require(err == noErr, AECreateDesc);
  540.  
  541.     //
  542.     // Make the object specifier with a null container
  543.     // (i.e., "file of <null>", or just "file")
  544.     //
  545.     nullDesc.descriptorType = typeNull;
  546.     nullDesc.dataHandle = NULL;    
  547.     err = CreateObjSpecifier(typeWildCard, &nullDesc, 
  548.                 formAlias, &hfsData, false, fileSpecifier);
  549.  
  550. AECreateDesc:
  551. NewAlias:
  552.     return err;
  553. }
  554.  
  555.  
  556. //----------------------------------------------------------------------------
  557. // MakePropertySpecifierForSpecifier
  558. //----------------------------------------------------------------------------
  559. OSErr MakePropertySpecifierForSpecifier(DescType property, 
  560.             AEDesc *ofSpecifier, AEDesc *propertySpecifier)
  561. {
  562.     OSErr        err;
  563.     AEDesc        keyData;
  564.     
  565.     //
  566.     // Create a 'type' AEDesc with the desired property
  567.     //
  568.     err = AECreateDesc(typeType, (Ptr) &property, sizeof(DescType), &keyData);
  569.     require(err == noErr, AECreateDesc);
  570.  
  571.     //
  572.     // With it create a property specifier for the object specifier
  573.     // passed to us.
  574.     //
  575.     err = CreateObjSpecifier(cProperty, ofSpecifier, 
  576.                 formPropertyID, &keyData, false, propertySpecifier);
  577.  
  578.     (void) AEDisposeDesc(&keyData);    
  579. AECreateDesc:
  580.     return err;
  581. }
  582.  
  583.  
  584. //----------------------------------------------------------------------------
  585. // CloneMoveDescList
  586. //----------------------------------------------------------------------------
  587. OSErr CloneMoveDescList(AEDescList *objsToMove, FSSpecPtr nuLocation, 
  588.             Point globalPt, Boolean replace, Boolean moveFlag)
  589. {
  590.     OSErr        err;
  591.     AppleEvent    finderEvent;
  592.     DescType    copyMove;
  593.     
  594.     if (moveFlag == true)
  595.         copyMove = kAEMove;
  596.     else
  597.         copyMove = kAEClone;
  598.  
  599.     //
  600.     // Make a Copy/Move Apple event to send to the Finder
  601.     //
  602.     err = MakeAppleEvent(kAECoreSuite, copyMove, &pFinderTarget, 
  603.                 &finderEvent);
  604.     require(err == noErr, MakeAppleEvent);
  605.  
  606.     //
  607.     // Put the objects to move in the Apple Event as the direct object
  608.     //
  609.     err = AEPutParamDesc(&finderEvent, keyDirectObject, objsToMove);    
  610.     require(err == noErr, AEPutParamDesc);
  611.  
  612.     //
  613.     // Put in where the Finder should move the items
  614.     //    
  615.     err = AEPutParamPtr(&finderEvent, keyAEInsertHere, typeFSS, 
  616.                     (Ptr) nuLocation, sizeof(FSSpec));
  617.     require(err == noErr, AEPutParamPtr1);
  618.     
  619.     //
  620.     // Specify whether the Finder should replace any duplicates
  621.     //
  622.     err = AEPutParamPtr(&finderEvent, keyAEReplacing, typeBoolean, 
  623.                     (Ptr) &replace, sizeof(Boolean));
  624.     require(err == noErr, AEPutParamPtr2);
  625.     
  626.     //
  627.     // And where the Finder should put the items
  628.     //
  629.     err = AEPutParamPtr(&finderEvent, keyGlobalPositionList, typeQDPoint, 
  630.                     (Ptr) &globalPt, sizeof(Point));
  631.     require(err == noErr, AEPutParamPtr3);
  632.     
  633.     //
  634.     // Send it and return any error
  635.     //
  636.     err = SendAppleEvent(&finderEvent, NULL,
  637.                     kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer);
  638.  
  639.     check(err == noErr);
  640.  
  641. AEPutParamPtr3:
  642. AEPutParamPtr2:
  643. AEPutParamPtr1:
  644. AEPutParamDesc:
  645.     (void) AEDisposeDesc(&finderEvent);
  646. MakeAppleEvent:    
  647.     return err;
  648. }
  649.  
  650.  
  651. //-----------------------------------------------------------------------------
  652. // GetDropFSSpec
  653. //
  654. // Given a DragReference, this returns an FSSpec for where the 
  655. // item was dropped.  In most cases this is an FSSpec to a directory, but
  656. // if TrackDrag returns a userCancelledErr, it may have been dropped onto
  657. // an application.
  658. //-----------------------------------------------------------------------------
  659. OSErr GetDropFSSpec(DragReference theDrag, FSSpecPtr dropSpec)
  660. {
  661.     OSErr    err;
  662.     AEDesc    theDesc, newDesc;
  663.  
  664.     err = GetDropLocation(theDrag, &theDesc);
  665.     require(err == noErr, GetDropLocation);
  666.  
  667.     err = AECoerceDesc(&theDesc, typeFSS, &newDesc);
  668.     require(err == noErr, AECoerceDesc);
  669.  
  670.     BlockMoveData(*newDesc.dataHandle, dropSpec, sizeof(FSSpec));
  671.  
  672.     (void) AEDisposeDesc(&newDesc);
  673. AECoerceDesc:
  674.     (void) AEDisposeDesc(&theDesc);
  675. GetDropLocation:
  676.     return err;
  677. }
  678.